import React from "react";
import { Tabs, Empty, Collapse } from "antd";
import { connect } from "react-redux";
import { IEditorProps } from "store/reducers/editor";
import { settingTabList, settingCompTableMap, attributeNameMap, customComponentMap } from "./config";
import { PropToForm, CombineFormItem } from "common/data/types";
import { pageFormPage } from "common/data/constants";
import { ADJUST_COMPONENT_SORT, SET_CURRENT_ELEMENT_PROPS, SET_PAGE_PROPS } from "store/constants";
import CompLayerSort from "../CompLayerSort";

import "./index.scss";

interface IComponentProps {
    is: string;
    [key: string]: any;
}
const Component: React.FC<IComponentProps> = ({ is, children, ...restProps }) => {
    try {
        const Comp = require("antd")[is] || Reflect.get(customComponentMap, is);
        if (!Comp) return null;
        return <Comp {...restProps}>{children}</Comp>;
    }catch{
        return null;
    }
};

interface ISettingTableProps {
    editor: IEditorProps;
    setCurrentComponentProps: (paylod: any) => void;
    adjustComponent: (components: any) => void;
    setPageProps: (payload: any) => void;
}
class SettingTable extends React.Component<ISettingTableProps> {

    // 处理组件属性编辑区配置数据
    handleComponentAttrConfig = (config: { [key: string]: PropToForm | CombineFormItem }, defaultValue: { [key: string]: string }) => {
        if(!config) return;
        const { editor } = this.props;
        const currentElement = editor.components.find(comp => comp.id === editor.currentElement);
        const newDefaultValue = {...defaultValue, ...currentElement?.props}
        const dataMap: { [key: string]: any } = {};
        Object.keys(config).forEach(key => {
            const cur = config[key];
            const { initialTransform } = cur as PropToForm;
            Reflect.set(dataMap, cur.type, [...dataMap?.[cur.type] || [], { 
                ...cur, 
                key,
                defaultValue: initialTransform ? initialTransform(newDefaultValue?.[key]) : newDefaultValue?.[key] }])
        })
        return dataMap;
    }

    // 处理设置组件属性
    handleSetComponentProps = (reply: any, value: any, key?: string) => {
        const { setCurrentComponentProps } = this.props;
        const { afterTransform } = reply || {};
        value = afterTransform ? afterTransform(value) : value;
        key = key ? key : reply?.key;
        if(key){
            setCurrentComponentProps({
                [key]: value
            })
        }
    }

    // 处理初始值：
    handleInitValue = (item: any, allDefaultValue?: any) => {
        const { initialTransform, defaultValue, propCombine, options } = item || {};
        if(propCombine){
            const initData = {};
            (options || []).forEach((cur: any) => {
                return Reflect.set(initData, cur?.key, Reflect.get(allDefaultValue, cur?.key) || "");
            })
            return initData;
        }
        return initialTransform ? initialTransform(defaultValue) : defaultValue
    }

    // 渲染编辑区折叠面板item
    renderComponentCollapsePanel = (editAttrData: any[], allValue?: any) => {
        return editAttrData.map((editItem: any) => {
            if(editItem?.form){
                return editItem?.form.map((childEditItem: any) => {
                    return (<div className="attribute-edit-item" key={`${editItem.key}-${childEditItem.key}`}>
                        { <label className="edit-label">{childEditItem?.label || ""}{ childEditItem?.label && <i>:</i> }</label> }
                        <div className="edit-component-wrapper">
                            <Component is={childEditItem.tag} {...childEditItem?.extraProps} {...childEditItem} onChange={(e: any) => {
                                const { defaultValue, combineFunc } = editItem;
                                const { key, afterTransform } = childEditItem || {};
                                if(combineFunc && defaultValue && key){
                                    let value = afterTransform ? afterTransform(e) : e;
                                    const combineValue = combineFunc(defaultValue, value, key);
                                    this.handleSetComponentProps(editItem, combineValue);
                                }
                            }} value={childEditItem?.initialTransform ? childEditItem?.initialTransform(editItem.defaultValue) : editItem.defaultValue} />
                        </div>
                    </div>)
                })
            }
            return (<div className="attribute-edit-item" key={editItem.key}>
                { <label className="edit-label">{editItem?.label || ""}{ editItem?.label && <i>:</i> }</label> }
                <div className="edit-component-wrapper">
                    <Component is={editItem.tag} 
                        onChange={(v: any, key?: string) => {
                            if(editItem?.propCombine){
                                this.handleSetComponentProps(editItem, v, key);
                                return;
                            }
                            this.handleSetComponentProps(editItem, v)
                        }} 
                        value={this.handleInitValue(editItem, allValue)}
                        {...editItem?.extraProps} 
                        {...editItem}
                    />
                </div>
            </div>)
        })
    }

    // 渲染组件属性编辑区
    renderComponentAttrTable = () => {
        const { editor } = this.props;
        if(!editor.currentElement){
           return <Empty /> 
        }
        const comp = editor.components.find(item => item.id === editor.currentElement);
        if(comp){
            const editProps = Reflect.get(settingCompTableMap, comp?.name);
            const configData = this.handleComponentAttrConfig(editProps?.editProps, editProps?.defaultValue);
            return <div>
                <Collapse defaultActiveKey="basic">
                    {
                        attributeNameMap.map(item => {
                            const editAttrData = configData?.[item.key];
                            if(!editAttrData) return null;
                            return <Collapse.Panel
                                header={item.title}
                                key={item.key}
                            >
                                {
                                   this.renderComponentCollapsePanel(editAttrData, comp.props)
                                }
                            </Collapse.Panel>
                        })
                    }
                </Collapse>
            </div>
        }
        return <Empty />
    }
    
    // 渲染图层列表区
    renderLayer = () => {
        const { components } = this.props.editor;
        const { adjustComponent } = this.props;
        if(components.length){
            return (<CompLayerSort components={components} onChange={(components: any) => adjustComponent(components)} />)
        }
        return <Empty />
    }

    // 渲染编辑页面样式的panel
    renderPageEditForm = () => {
        const { defaultPageStyle } = this.props.editor;
        const { setPageProps } = this.props;
        return <div className="page-edit-wrapper">
            {
                Object.keys(pageFormPage).map(key => {
                    const config = Reflect.get(pageFormPage, key);
                    return (<div className="attribute-edit-item" key={key}>
                    { config?.label ? <label className="edit-label">{config?.label || ""}<i>:</i></label> : null }
                    <div className="edit-component-wrapper">
                        <Component is={config.tag} 
                            onChange={(v: any) => {
                                const value = config.afterTransform ? config.afterTransform(v) : v;
                                setPageProps({[key]: value})
                            }} 
                            value={config?.initialTransform ? config.initialTransform(Reflect.get(defaultPageStyle, key)) : Reflect.get(defaultPageStyle, key) || ""}
                            {...config?.extraProps} 
                            {...config}
                        />
                    </div>
                </div>)
                })
            }
        </div>
    }

    renderTabPane = (key: string) => {
        switch(key){
            case "comp-attribute":
                return this.renderComponentAttrTable();
            case "layer-setting":
                return this.renderLayer();
            case "page-setting":
                return this.renderPageEditForm();
            default:
                return <Empty />
        }
    }

    render(){
        return (<div className="setting-table-wrapper">
            <Tabs defaultActiveKey="">
                {
                    settingTabList.tabList.map(item => {
                        return <Tabs.TabPane
                            tab={item.title}
                            key={item.key}
                        >
                            { this.renderTabPane(item.key) }
                        </Tabs.TabPane>
                    })
                }
            </Tabs>
        </div>)
    }
}

export default connect((state: any) => {
    return { editor: state.editor }
}, (dispatch) => {
    return {
        setCurrentComponentProps: (payload: any) => dispatch({type: SET_CURRENT_ELEMENT_PROPS, payload}),
        adjustComponent: (components: any) => dispatch({type: ADJUST_COMPONENT_SORT, payload: components}),
        setPageProps: (payload: any) => dispatch({type: SET_PAGE_PROPS, payload})
    }
})(SettingTable);